package com.ch02.server;

import com.ch02.entity.MessageData;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.websocket.OnClose;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.Session;
import jakarta.websocket.server.ServerEndpoint;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName WebSocket
 * @Description 聊天室服务端（configurator属性设置握手处理器）
 * @Author Kx
 * @Date 2025/9/18 9:57
 * @Version 1.0
 */
@ServerEndpoint(value = "/connect", configurator = HandshakeHandler.class)
public class WebSocket {

    // 存储用户信息
    private static final Map<String, Session> users = new HashMap<>();

    // json转换器
    private static final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * @author: kx
     * @date: 2025/9/18 13:51
     * @param session : 会话对象（用户信息存储在内）
     * @description: 用户上线调用此方法
    */
    @OnOpen
    public void onOpen(Session session) {
        // 统计在线人数
        synchronized (this) {
            // 获取用户信息
            String user = (String) session.getUserProperties().get("user");
            // 把用户信息存储到集合中
            users.put(user, session);
        }
        getNumber();
    }

    /**
     * @author: kx
     * @date: 2025/9/18 13:54
     * @param session : 会话对象
     * @param message : 消息
     * @description: 接收客户端发送的消息并执行群发（发送给所有人）
    */
    @OnMessage
    public void onMessage(Session session, String message) {
        // 获取发送人
        String user = (String) session.getUserProperties().get("user");
        // 获取当前时间戳
        LocalDateTime now = LocalDateTime.now();
        // 格式化时间
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");
        // 转换成正常时间
        String time = now.format(dateTimeFormatter);
        // 拼接消息对象
        MessageData messageData = new MessageData();
        messageData.setUser(user);
        messageData.setMessage(message);
        messageData.setTime(time);
        // 将消息对象转换为JSON字符串再发送给所有人
        try {
            String data = objectMapper.writeValueAsString(messageData);
            sendAll(data);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @author: kx
     * @date: 2025/9/18 14:57
     * @param message : 消息
     * @description: 群发消息
    */
    private void sendAll(String message) {
        for (Session session : users.values()) {
            try {
                // 发送消息给用户
                session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                throw new RuntimeException("发送失败" + e);
            }
        }
    }

    /**
     * @author: kx
     * @date: 2025/9/18 14:58
     * @description: 用户离线时触发
    */
    @OnClose
    public void onClose(Session session) {
        // 统计在线人数
        synchronized (this) {
            // 获取用户信息
            String user = (String) session.getUserProperties().get("user");
            // 清除集合中用户信息
            users.remove(user);
        }
        getNumber();
    }

    /**
     * @author: kx
     * @date: 2025/9/18 16:20
     * @description: 发送在线人数
    */
    public void getNumber() {
        for (Session session : users.values()) {
            // 判断是否处于运行中状态
            if (session.isOpen()) {
                try {
                    session.getBasicRemote().sendText("当前在线人数： " +  users.size());
                } catch (IOException e) {
                    throw new RuntimeException("发送失败" + e);
                }
            }
        }
    }
}
